package com.lock.pessimisticLock.service;

import com.lock.pessimisticLock.model.Account;
import com.utils.HibernateUtil;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class BusinessService extends Thread {
    public SessionFactory sessionFactory = new HibernateUtil().getSessionFactory();

    private String transactionType;
    private Log log;

    public BusinessService() {

    }

    public BusinessService(String transactionType, Log log) {
        this.transactionType = transactionType;
        this.log = log;
    }

    public void run() {
        try {
            if (transactionType.equals("withdraw")) {
                withdraw();
            } else {
                transferCheck();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void withdraw() throws Exception {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {

            tx = session.beginTransaction();
            log.write("withdraw():开始事务");
            Thread.sleep(500);

            Account account = (Account) session.get(Account.class, 1L, LockMode.UPGRADE);
//      Account account=(Account)session.get(Account.class, 1L);

            log.write("withdraw():查询到存款余额为：balance=" + account.getBalance());
            Thread.sleep(500);

            account.setBalance(account.getBalance() - 100);
            log.write("withdraw():取出100元，把存款余额改为：" + account.getBalance());

            log.write("withdraw():提交事务");
            tx.commit();
            Thread.sleep(500);

        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            throw e;
        } finally {
            session.close();
        }
    }

    private void transferCheck() throws Exception {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {

            tx = session.beginTransaction();
            log.write("transferCheck():开始事务");
            Thread.sleep(500);

            Account account = (Account) session.get(Account.class, 1L, LockMode.UPGRADE);
//      Account account=(Account)session.get(Account.class, 1L);

            log.write("transferCheck():查询到存款余额为：balance=" + account.getBalance());
            Thread.sleep(500);

            account.setBalance(account.getBalance() + 100);
            log.write("transferCheck():汇入100元，把存款余额改为：" + account.getBalance());

            log.write("transferCheck():提交事务");
            tx.commit();
            Thread.sleep(500);

        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            throw e;
        } finally {
            session.close();
        }
    }

    private void registerAccount() {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            Account account = new Account();
            account.setName("Tom");
            account.setBalance(1000);
            session.save(account);
            tx.commit();

        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            throw e;
        } finally {
            session.close();
        }
    }

    public static void main(String args[]) throws Exception {
        SessionFactory sessionFactory = null;
        Log log = new Log();
        Thread withdrawThread = new BusinessService("withdraw", log);
        Thread transferCheckThread = new BusinessService("transferCheck", log);

//        ((BusinessService) withdrawThread).registerAccount();//第一种插入数据法

//        BusinessService businessService = new BusinessService();//第二种插入数据法
//        businessService.registerAccount();

        withdrawThread.start();
        transferCheckThread.start();

        while (withdrawThread.isAlive() || transferCheckThread.isAlive()) {
            Thread.sleep(100);
        }
        log.print();
    }
}

